package org.jinghouyu.caculator.engine;

import java.util.ArrayList;
import java.util.List;

/**
 * 表达式
 * @author liujingyu
 *
 */
public abstract class Expression {

	private List<Expression> subExpressions;
	
	public Expression getSubExpression(int i) {
		return subExpressions.get(i);
	}
	
	public List<Expression> getSubExpressions() {
		return subExpressions;
	}
	
	public Object caculate() {
		if(subExpressions == null || subExpressions.size() == 0) {
			return _caculate();
		}
		Object[] values = new Object[subExpressions.size()];
		for(int i = 0; i < subExpressions.size(); i++) {
			values[i] = subExpressions.get(i).caculate();
		}
		return _caculate(values);
	}
	
	protected abstract Object _caculate(Object... values);
	
	public Expression addSubExpression(Expression expression) {
		if(subExpressions == null) {
			synchronized(this) {
				if(subExpressions == null) {
					subExpressions = createSubExpressions();
				}
			}
		}
		subExpressions.add(expression);
		return this;
	}
	
	private static List<Expression> createSubExpressions() {
		return new ArrayList<>();
	}
	
	protected static double getDouble(Object value) {
		if(value == null) throw new ExpressionException();
		if(value instanceof Number) return ((Number) value).doubleValue();
		throw new ExpressionException();
	}
	
	protected static Object getValue(Object[] values, int i) {
		if(values == null) return null;
		if(i >= values.length) return null;
		return values[i];
	}
}